package com.tianji.learning.utils;

import com.tianji.common.domain.R;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.JsonUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.learning.domain.LearningLesson;
import com.tianji.learning.domain.LearningRecord;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.LearningLessonService;
import com.tianji.learning.service.LearningRecordService;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.DelayQueue;

/**
 * @Description LearningRecordDelayTaskHandler
 * 消费消息
 * 添加记录到redis和延迟队列中
 * 查缓存中的记录
 * 删缓存中的记录
 * @Author WJH
 * @Date 2024-12-23
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class LearningRecordDelayTaskHandler {
    private static final String RECORD_CACHE_PREFIX="record:cache";
    @Autowired
    private StringRedisTemplate redisTemplate;
    private  DelayQueue<DelayTask<LearningRecord>> delayQueue=new DelayQueue<>();

    @Autowired
    private LearningLessonService lessonService;

    @Autowired
    @Lazy
    private LearningRecordService recordService;
    private static volatile boolean begin=true;

    @PostConstruct
    public void init(){
        CompletableFuture.runAsync(this::handleDelayTask);
    }

/*    *
    优雅停止*/

    @PreDestroy
    public void destory(){
        begin=false;
    }


/*
    *
     * 消费延迟消息，项目启动的时候直接调用*/

    public void handleDelayTask(){
        while (begin){
            try {
                //从延迟队列中取
                DelayTask<LearningRecord> task = delayQueue.take();
                LearningRecord recordData= task.getData();
                if(ObjectUtils.isNull(recordData)){
                    continue;
                }
                //从缓存中取
                LearningRecord obj = readRecordCache(recordData.getLessonId(), recordData.getSectionId());
                if(ObjectUtils.isNull(obj)){
                    continue;
                }
                LearningRecord record = JsonUtils.toBean(obj.toString(), LearningRecord.class);
                //判断moment属性值是否一致,如果一致证明用户不看了，再最终操作数据库
                if(recordData.getMoment().equals(record.getMoment())){
                    //更新学习记录
                    boolean b = recordService.lambdaUpdate()
                            .eq(LearningRecord::getId, record.getId())
                            .set(LearningRecord::getMoment, record.getMoment())
                            .update();
                    if(!b){
                        throw new DbException("更新学习记录失败");
                    }
                    //更新课表
                    boolean b1 = lessonService.lambdaUpdate()
                            .eq(LearningLesson::getId, record.getLessonId())
                            .set(LearningLesson::getLatestSectionId, record.getSectionId())
                            .set(LearningLesson::getLatestLearnTime, LocalDateTime.now().minusSeconds(20))
                            .update();
                    if(!b1){
                        throw new DbException("更新课表失败");
                    }
                }

            } catch (InterruptedException e) {
                log.info("");
            }
        }
    }
/*
    *
     * 添加播放记录到redis中，并且添加到延迟队列中*/

    public void add2Cache(LearningRecord record){
        writeRecordToRedis(record);
        DelayTask<LearningRecord> delayTask = new DelayTask<>(record, Duration.ofSeconds(20));
        delayQueue.add(delayTask);
    }
    public void writeRecordToRedis(LearningRecord record){
        String redisKey=RECORD_CACHE_PREFIX+record.getLessonId();
        String hashKey=record.getSectionId().toString();
        String recordJsonStr = JsonUtils.toJsonStr(record);
        redisTemplate.opsForHash().put(redisKey,hashKey,recordJsonStr);
        redisTemplate.expire(redisKey, Duration.ofMinutes(30));
    }

    public LearningRecord readRecordCache(Long lessonId, Long sectionId){
        try {
            // 1.读取Redis数据
            String redisKey=RECORD_CACHE_PREFIX+lessonId;
            String hashKey=sectionId.toString();
            Object obj = redisTemplate.opsForHash().get(redisKey, hashKey);
            if(ObjectUtils.isNull(obj)){
                return null;
            }
            LearningRecord record = JsonUtils.toBean(obj.toString(), LearningRecord.class);
            return record;
        } catch (Exception e) {
            log.error("缓存读取异常", e);
            return null;
        }
    }
    public void deleteRecordFromRedis(Long lessionId,Long sectionId){
        String redisKey=RECORD_CACHE_PREFIX+lessionId;
        String hashKey=sectionId.toString();
        redisTemplate.opsForHash().delete(redisKey,hashKey);
    }

}
